home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 409_01 / svgac.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-10-22  |  25.1 KB  |  733 lines

  1. /****************************************************************************
  2. *
  3. *                          SuperVGA Test Library
  4. *
  5. *                   Copyright (C) 1993 SciTech Software
  6. *                           All rights reserved.
  7. *
  8. * Filename:     $RCSfile: svgac.c $
  9. * Version:      $Revision: 1.3 $
  10. *
  11. * Language:     ANSI C
  12. * Environment:  IBM PC (MSDOS)
  13. *
  14. * Description:  Simple library to collect together the functions in the
  15. *               SuperVGA test library for use in other C programs. The
  16. *               support is reasonably low level, so you can do what you
  17. *               want. The set of routines in this source file are general
  18. *               SuperVGA routines and are independant of the video mode
  19. *               selected.
  20. *
  21. *               MUST be compiled in the large model.
  22. *
  23. * $Id: svgac.c 1.3 1993/10/22 08:58:40 kjb release $
  24. *
  25. ****************************************************************************/
  26.  
  27. #include <string.h>
  28. #include <dos.h>
  29. #include <stdlib.h>
  30. #include "svga.h"
  31. #include "vesavbe.h"
  32.  
  33. /*---------------------------- Global Variables ---------------------------*/
  34.  
  35. #define MAXMODES    50              /* Maximum modes available in list  */
  36.  
  37. int     maxx,maxy,memory;
  38. long    maxcolor,defcolor;
  39. int     maxpage,bytesperline;
  40. uchar    redMask,greenMask,blueMask;
  41. int        redPos,redAdjust;
  42. int        greenPos,greenAdjust;
  43. int        bluePos,blueAdjust;
  44. bool    twobanks = false,extendedflipping = false,widedac = false;
  45. short   modeList[MAXMODES];
  46. char    OEMString[80];
  47.  
  48. int     oldMode;                    /* Old video mode number            */
  49. bool    old50Lines;                 /* Was old mode 80x50?              */
  50. int     curBank;                    /* Current read/write bank          */
  51. int     bankAdjust;                 /* Bank granularity adjust factor   */
  52. long    pagesize;                   /* Page size for current mode       */
  53. void    *bankSwitch;                /* Pointer to bank switch routine   */
  54. void    *writeBank;                 /* Relocated write bank routine     */
  55. void    *readBank;                  /* Relocated read bank routine      */
  56. void    *pageFlip;                  /* Relocated page flip routine      */
  57. void     (*putPixel)(int x,int y,long color);
  58. void     (*clear)(void);
  59.  
  60. /*----------------------------- Implementation ----------------------------*/
  61.  
  62. /* Declare all video mode dependent routines */
  63.  
  64. void _putPixel16(int x,int y,long color);
  65. void _putPixel256(int x,int y,long color);
  66. void _putPixel32k(int x,int y,long color);
  67. void _putPixel64k(int x,int y,long color);
  68. void _putPixel16m(int x,int y,long color);
  69. void _clear16(void);
  70. void _clear256(void);
  71. void _clear32k(void);
  72. void _clear64k(void);
  73. void _clear16m(void);
  74.  
  75. PRIVATE bool checkVESAPageFlip(void)
  76. /****************************************************************************
  77. *
  78. * Function:     checkVESAPageFlip
  79. * Returns:      True if VBE supports page flipping.
  80. *
  81. * Description:  Determines if the VESA VBE supports extended page
  82. *               flipping or not. Assume a suitable video mode has already
  83. *               been initialised.
  84. *
  85. ****************************************************************************/
  86. {
  87.     union REGS  regs;
  88.  
  89.     regs.x.ax = 0x4F07;         /* Set display start service            */
  90.     regs.x.bx = 0;              /* BH := 0, BL := 0 (set display start) */
  91.     regs.x.cx = 0;              /* Leftmost pixel in line               */
  92.     regs.x.dx = 0;              /* First displayed scanline             */
  93.     int86(0x10,®s,®s);
  94.     if (regs.x.ax != 0x004F)
  95.         return false;           /* Function failed, not page flip       */
  96.  
  97.     regs.x.ax = 0x4F07;         /* Get display start service            */
  98.     regs.x.bx = 1;              /* BH := 0, BL := 1 (get display start) */
  99.     int86(0x10,®s,®s);
  100.     if (regs.x.ax != 0x004F)
  101.         return false;           /* Function failed, not page flip       */
  102.     if (regs.h.bh != 0)
  103.         return false;
  104.     if (regs.x.cx != 0)
  105.         return false;
  106.     if (regs.x.dx != 0)
  107.         return false;
  108.     return true;
  109. }
  110.  
  111. bool checkWideDAC(void)
  112. /****************************************************************************
  113. *
  114. * Function:     checkWideDAC
  115. * Returns:      True if 8 bit wide DAC is supported.
  116. *
  117. * Description:  Tests to see if the VBE BIOS supports an 8 bit wide
  118. *               DAC. This assumes the video card is in an appropriate
  119. *               video mode before being called.
  120. *
  121. ****************************************************************************/
  122. {
  123.     union REGS  regs;
  124.     short       bits;
  125.  
  126.     regs.x.ax = 0x4F08;         /* Set DAC service                      */
  127.     regs.x.bx = 0x0800;         /* BH := 8, BL := 0 (set DAC width)     */
  128.     int86(0x10,®s,®s);
  129.     if (regs.x.ax != 0x004F)
  130.         return false;           /* Function failed, no wide dac         */
  131.     if (regs.h.bh == 6)
  132.         return false;
  133.     regs.x.ax = 0x4F08;
  134.     regs.x.bx = 0x0001;         /* Get DAC width (should now be 8)      */
  135.     int86(0x10,®s,®s);
  136.     if (regs.x.ax != 0x004F)
  137.         return false;
  138.     bits = regs.h.bh;
  139.     regs.x.ax = 0x4F08;
  140.     regs.x.bx = 0x0600;
  141.     int86(0x10,®s,®s);    /* Restore to 6 bit DAC                 */
  142.     if (regs.x.ax != 0x004F)
  143.         return false;
  144.  
  145.     return (bits == 8);
  146. }
  147.  
  148. PUBLIC int initSuperVGA(void)
  149. /****************************************************************************
  150. *
  151. * Function:     initSuperVGA
  152. * Returns:      VBE version number for the SuperVGA (0 if no SuperVGA).
  153. *
  154. * Description:  Detects if a VESA VBE compliant SuperVGA is out there, and
  155. *               initialises the library if one is. The VBE version number
  156. *               is specified with the major version number in the high
  157. *               byte and the minor version number in the low byte. So
  158. *               version 1.2 is the number 0x102.
  159. *
  160. ****************************************************************************/
  161. {
  162.     VgaInfoBlock    vgaInfo;
  163.     ModeInfoBlock   modeInfo;
  164.     union REGS      regs;
  165.     struct SREGS    sregs;
  166.     short           *p,i;
  167.  
  168.     sregs.es = SEG(&vgaInfo);
  169.     regs.x.di = OFF(&vgaInfo);
  170.     regs.x.ax = 0x4F00;
  171.     int86x(0x10,®s,®s,&sregs);    /* Get SuperVGA information     */
  172.     if (regs.x.ax != 0x004F)
  173.         return false;
  174.     if (strncmp(vgaInfo.VESASignature,"VESA",4) != 0)
  175.         return false;
  176.  
  177.     /* Copy relavent information from the mode block into our globals.
  178.      * Note that the video mode list _may_ be built in the information
  179.      * block that we have passed, so we _must_ copy this from here
  180.      * into our our storage if we want to continue to use it. Note
  181.      * that we filter out the mode 0x6A, which some BIOSes include as
  182.      * well as the 0x102 mode for 800x600x16.
  183.      */
  184.  
  185.     for (i = 0,p = vgaInfo.VideoModePtr; *p != -1; p++,i++) {
  186.         if (*p != 0x6A)
  187.             modeList[i] = *p;
  188.         }
  189.     modeList[i] = -1;
  190.     memory = vgaInfo.TotalMemory * 64;
  191.     strcpy(OEMString,vgaInfo.OEMStringPtr);
  192.  
  193.     /* Determine if the board supports separate read/write banks and
  194.      * extended page flipping. Some VESA VBE's require the card to be
  195.      * in a graphics mode for these tests to work, so we find a suitable
  196.      * mode and use that.
  197.      */
  198.  
  199.     for (p = modeList; *p != -1; p++) {
  200.         sregs.es = SEG(&modeInfo);
  201.         regs.x.di = OFF(&modeInfo);
  202.         regs.x.ax = 0x4F01;
  203.         regs.x.cx = *p;
  204.         int86x(0x10,®s,®s,&sregs);    /* Get SuperVGA mode info   */
  205.         if (regs.x.ax == 0x004F &&
  206.                 (modeInfo.MemoryModel == 3 || modeInfo.MemoryModel == 4)) {
  207.             modeInfo.WinBAttributes &= 0x7;
  208.             twobanks = (modeInfo.WinBAttributes == 0x3);
  209.             setSuperVGAMode(*p);
  210.             extendedflipping = checkVESAPageFlip();
  211.             widedac = checkWideDAC();
  212.             restoreMode();
  213.             break;
  214.             }
  215.         }
  216.  
  217.     return vgaInfo.VESAVersion;
  218. }
  219.  
  220. PRIVATE void computePageInfo(ModeInfoBlock *modeInfo,int *maxpage,
  221.     long *pagesize)
  222. /****************************************************************************
  223. *
  224. * Function:     computePageInfo
  225. * Parameters:   modeInfo    - Pointer to valid mode information block
  226. *               maxpage     - Number of display pages - 1
  227. *               pagesize    - Size of each logical display page in bytes
  228. *
  229. * Description:  Computes the number of image pages and size of each image
  230. *               page for a specified video mode.
  231. *
  232. ****************************************************************************/
  233. {
  234.     long    memsize,size;
  235.  
  236.     if (extendedflipping)
  237.         memsize = memory * 1024L;
  238.     else
  239.         memsize = 256 * 1024L;      /* Use only 256k to compute pages   */
  240.  
  241.     size = (long)modeInfo->BytesPerScanLine * (long)modeInfo->YResolution;
  242.     if (modeInfo->BitsPerPixel == 4) {
  243.         /* We have a 16 color video mode, so round up the page size to
  244.          * 8k, 16k, 32k or 64k boundaries depending on how large it is.
  245.          */
  246.  
  247.         size = (size + 0x1FFFL) & 0xFFFFE000L;
  248.         if (size != 0x2000) {
  249.             size = (size + 0x3FFFL) & 0xFFFFC000L;
  250.             if (size != 0x4000) {
  251.                 size = (size + 0x7FFFL) & 0xFFFF8000L;
  252.                 if (size != 0x8000)
  253.                     size = (size + 0xFFFFL) & 0xFFFF0000L;
  254.                 }
  255.             }
  256.         }
  257.     else
  258.         size = (size + 0xFFFFL) & 0xFFFF0000L;
  259.  
  260.     if (modeInfo->MemoryModel == memPL)
  261.         memsize /= 4;
  262.     if (size <= memsize)
  263.         *maxpage = (memsize / size) - 1;
  264.     else
  265.         *maxpage = 0;
  266.     *pagesize = size;
  267. }
  268.  
  269. PUBLIC bool getSuperVGAModeInfo(int mode,int *xres,int *yres,
  270.     int *bytesperline,int *bitsperpixel,int *memmodel,int *maxpage,
  271.     long *pagesize)
  272. /****************************************************************************
  273. *
  274. * Function:     getSuperVGAModeInfo
  275. * Parameters:   mode            - Mode to get information about
  276. *               xres            - Place to store x resolution
  277. *               yres            - Place to store y resolution
  278. *               bytesperline    - Bytes per scanline
  279. *               bitsperpixel    - Place to store bits per pixel (2^n colors)
  280. *               memmodel        - Memory model for mode (planar, packed etc)
  281. *               maxpage         - Number of display pages - 1
  282. *               pagesize        - Size of each logical display page in bytes
  283. * Returns:      True if mode number was valid, false if not.
  284. *
  285. * Description:  Obtains information about a specific video mode from the
  286. *               VBE. You should use this function to find the video mode
  287. *               you wish to set, as the new VBE 2.0 mode numbers may be
  288. *               completely arbitrary.
  289. *
  290. ****************************************************************************/
  291. {
  292.     ModeInfoBlock   modeInfo;
  293.     union REGS      regs;
  294.     struct SREGS    sregs;
  295.  
  296.     if (mode <= 0x13) {
  297.         /* This is a standard VGA mode, so fill in the required information
  298.          * ourselves.
  299.          */
  300.  
  301.         switch (mode) {
  302.             case 0x0D:
  303.                 modeInfo.XResolution = 320;
  304.                 modeInfo.YResolution = 200;
  305.                 modeInfo.BytesPerScanLine = 40;
  306.                 modeInfo.BitsPerPixel = 4;
  307.                 modeInfo.MemoryModel = memPL;
  308.                 break;
  309.             case 0x0E:
  310.                 modeInfo.XResolution = 640;
  311.                 modeInfo.YResolution = 200;
  312.                 modeInfo.BytesPerScanLine = 80;
  313.                 modeInfo.BitsPerPixel = 4;
  314.                 modeInfo.MemoryModel = memPL;
  315.                 break;
  316.             case 0x10:
  317.                 modeInfo.XResolution = 640;
  318.                 modeInfo.YResolution = 350;
  319.                 modeInfo.BytesPerScanLine = 80;
  320.                 modeInfo.BitsPerPixel = 4;
  321.                 modeInfo.MemoryModel = memPL;
  322.                 break;
  323.             case 0x12:
  324.                 modeInfo.XResolution = 640;
  325.                 modeInfo.YResolution = 480;
  326.                 modeInfo.BytesPerScanLine = 80;
  327.                 modeInfo.BitsPerPixel = 4;
  328.                 modeInfo.MemoryModel = memPL;
  329.                 break;
  330.             case 0x13:
  331.                 modeInfo.XResolution = 320;
  332.                 modeInfo.YResolution = 200;
  333.                 modeInfo.BytesPerScanLine = 320;
  334.                 modeInfo.BitsPerPixel = 8;
  335.                 modeInfo.MemoryModel = memPK;
  336.                 break;
  337.             default:
  338.                 return false;
  339.             }
  340.         }
  341.     else {
  342.         /* This is a VESA mode, so call the BIOS to get information about
  343.          * it.
  344.          */
  345.  
  346.         sregs.es = SEG(&modeInfo);
  347.         regs.x.di = OFF(&modeInfo);
  348.         regs.x.ax = 0x4F01;
  349.         regs.x.cx = mode;
  350.         int86x(0x10,®s,®s,&sregs);    /* Get mode information         */
  351.         if (regs.x.ax != 0x004F)
  352.             return false;
  353.         if ((modeInfo.ModeAttributes & 0x1) == 0)
  354.             return false;
  355.         }
  356.     *xres = modeInfo.XResolution;
  357.     *yres = modeInfo.YResolution;
  358.     *bytesperline = modeInfo.BytesPerScanLine;
  359.     *memmodel = modeInfo.MemoryModel;
  360.     *bitsperpixel = modeInfo.BitsPerPixel;
  361.     if (*memmodel == memPK && *bitsperpixel > 8) {
  362.         /* Support old style definitions, which some BIOS'es still use :-( */
  363.         *memmodel = memRGB;
  364.         switch (*bitsperpixel) {
  365.             case 15:
  366.                 redMask = 0x1F;        redPos = 10;    redAdjust = 3;
  367.                 greenMask = 0x1F;    greenPos = 5;    greenAdjust = 3;
  368.                 blueMask = 0x1F;    bluePos = 0;    blueAdjust = 3;
  369.                 break;
  370.             case 16:
  371.                 redMask = 0x1F;        redPos = 11;    redAdjust = 3;
  372.                 greenMask = 0x3F;    greenPos = 5;    greenAdjust = 2;
  373.                 blueMask = 0x1F;    bluePos = 0;    blueAdjust = 3;
  374.                 break;
  375.             case 24:
  376.                 redMask = 0xFF;        redPos = 16;    redAdjust = 0;
  377.                 greenMask = 0xFF;    greenPos = 8;    greenAdjust = 0;
  378.                 blueMask = 0xFF;    bluePos = 0;    blueAdjust = 0;
  379.                 break;
  380.             }
  381.         }
  382.     else if (*memmodel == memRGB) {
  383.         /* Convert the 32k direct color modes of VBE 1.2+ BIOSes to
  384.          * be recognised as 15 bits per pixel modes.
  385.          */
  386.  
  387.         if (*bitsperpixel == 16 && modeInfo.RsvdMaskSize == 1)
  388.             *bitsperpixel = 15;
  389.  
  390.         /* Save direct color info mask positions etc */
  391.  
  392.         redMask = (0xFF >> (redAdjust = 8 - modeInfo.RedMaskSize));
  393.         redPos = modeInfo.RedFieldPosition;
  394.         greenMask = (0xFF >> (greenAdjust = 8 - modeInfo.GreenMaskSize));
  395.         greenPos = modeInfo.GreenFieldPosition;
  396.         blueMask = (0xFF >> (blueAdjust = 8 - modeInfo.BlueMaskSize));
  397.         bluePos = modeInfo.BlueFieldPosition;
  398.         }
  399.     if (mode == 0x13 && !extendedflipping)
  400.         *maxpage = 0;
  401.     else
  402.         computePageInfo(&modeInfo,maxpage,pagesize);
  403.     return true;
  404. }
  405.  
  406. typedef struct {
  407.     short   writeBankLen;
  408.     void    *writeBank;
  409.     short   readBankLen;
  410.     void    *readBank;
  411.     short   newPageLen;
  412.     void    *newPage;
  413.     } PMInfoBlock;
  414.  
  415. PUBLIC bool setSuperVGAMode(int mode)
  416. /****************************************************************************
  417. *
  418. * Function:     setSuperVGAMode
  419. * Parameters:   mode    - SuperVGA video mode to set.
  420. * Returns:      True if the mode was set, false if not.
  421. *
  422. * Description:  Attempts to set the specified video mode. This routine
  423. *               assumes that the library and SuperVGA have been initialised
  424. *               with the initSuperVGA() routine first.
  425. *
  426. ****************************************************************************/
  427. {
  428.     ModeInfoBlock   modeInfo;
  429.     PMInfoBlock     *pmInfo = (PMInfoBlock*)&modeInfo;
  430.     union REGS      regs;
  431.     struct SREGS    sregs;
  432.     int             bitsperpixel,memmodel;
  433.  
  434.     regs.x.ax = 0x0F00;
  435.     int86(0x10,®s,®s);
  436.     oldMode = regs.x.ax & 0x7F;         /* Save old video mode          */
  437.     old50Lines = false;                 /* Default to 25 line mode      */
  438.     if (oldMode == 0x3) {
  439.         regs.x.ax = 0x1130;
  440.         regs.x.bx = 0;
  441.         regs.x.dx = 0;
  442.         int86(0x10,®s,®s);
  443.         old50Lines = (regs.h.dl == 49);
  444.         }
  445.  
  446.     regs.x.ax = 0x4F02;
  447.     regs.x.bx = mode;
  448.     int86(0x10,®s,®s);            /* Set the video mode           */
  449.     if (regs.x.ax != 0x004F)
  450.         return false;
  451.  
  452.     getSuperVGAModeInfo(mode,&maxx,&maxy,&bytesperline,&bitsperpixel,
  453.         &memmodel,&maxpage,&pagesize);
  454.     maxx--; maxy--;
  455.  
  456.     /* Now set up the vectors to the correct routines for the video
  457.      * mode type.
  458.      */
  459.  
  460.     switch (bitsperpixel) {
  461.         case 4:
  462.             putPixel = _putPixel16;
  463.             clear = _clear16;
  464.             maxcolor = defcolor = 15;
  465.             break;
  466.         case 8:
  467.             putPixel = _putPixel256;
  468.             clear = _clear256;
  469.             maxcolor = 255;
  470.             defcolor = 15;
  471.             break;
  472.         case 15:
  473.             putPixel = _putPixel32k;
  474.             clear = _clear32k;
  475.             maxcolor = defcolor = 0x7FFF;
  476.             break;
  477.         case 16:
  478.             putPixel = _putPixel64k;
  479.             clear = _clear64k;
  480.             maxcolor = defcolor = 0xFFFF;
  481.             break;
  482.         case 24:
  483.             putPixel = _putPixel16m;
  484.             clear = _clear16m;
  485.             maxcolor = defcolor = 0xFFFFFF;
  486.             break;
  487.         }
  488.  
  489.     if (mode <= 0x13) {
  490.         /* This is a normal VGA style mode, so we need to determine the
  491.          * correct information for bank switching from the BIOS
  492.          */
  493.  
  494.         if (mode == 0x13)
  495.             mode = 0x101;
  496.         else
  497.             mode = 0x102;
  498.         }
  499.     sregs.es = SEG(&modeInfo);
  500.     regs.x.di = OFF(&modeInfo);
  501.     regs.x.ax = 0x4F01;
  502.     regs.x.cx = mode;
  503.     int86x(0x10,®s,®s,&sregs);    /* Get mode information         */
  504.     bankAdjust = 64 / modeInfo.WinGranularity;
  505.     curBank = -1;
  506.     bankSwitch = modeInfo.WinFuncPtr;
  507.  
  508.     /* Now set up the vectors to the appropriate bank switching routines.
  509.      * If the Universal VESA VBE is installed, we can move the bank
  510.      * switching routines from there into our own code space for speed
  511.      * (especially under protected mode).
  512.      */
  513.  
  514.     sregs.es = SEG(&modeInfo);
  515.     regs.x.di = OFF(&modeInfo);
  516.     regs.x.ax = 0x4F01;
  517.     regs.x.cx = -1;
  518.     int86x(0x10,®s,®s,&sregs);    /* Get mode information         */
  519.     writeBank = readBank = pageFlip = NULL;
  520.     if (regs.x.ax == 0x004F && regs.x.cx == 0xCABD) {
  521.         /* The Universal VESA VBE is there and functioning, so copy the
  522.          * routines onto the heap and execute from there.
  523.          */
  524.  
  525.         writeBank = malloc(pmInfo->writeBankLen);
  526.         memcpy(writeBank,pmInfo->writeBank,pmInfo->writeBankLen);
  527.         if (pmInfo->readBankLen > 0) {
  528.             readBank = malloc(pmInfo->readBankLen);
  529.             memcpy(readBank,pmInfo->readBank,pmInfo->readBankLen);
  530.             }
  531.         pageFlip = malloc(pmInfo->newPageLen);
  532.         memcpy(pageFlip,pmInfo->newPage,pmInfo->newPageLen);
  533.         }
  534.  
  535.     return true;
  536. }
  537.  
  538. PUBLIC void restoreMode(void)
  539. /****************************************************************************
  540. *
  541. * Function:     restoreMode
  542. *
  543. * Description:  Restore the previous video mode in use before the SuperVGA
  544. *               mode was set. This routine will also restore the 50 line
  545. *               display mode if this mode was previously set.
  546. *
  547. ****************************************************************************/
  548. {
  549.     union REGS  regs;
  550.  
  551.     regs.x.ax = oldMode;
  552.     int86(0x10,®s,®s);            /* Set the old video mode       */
  553.     if (old50Lines) {
  554.         regs.x.ax = 0x1112;
  555.         regs.x.bx = 0;
  556.         int86(0x10,®s,®s);        /* Restore 50 line mode         */
  557.         }
  558. }
  559.  
  560. void setSuperVGADisplayStart(int x,int y)
  561. /****************************************************************************
  562. *
  563. * Function:     setDisplayStart
  564. * Parameters:   x,y - Position of the first pixel to display
  565. *
  566. * Description:  Sets the new starting display position to implement
  567. *               hardware scrolling.
  568. *
  569. ****************************************************************************/
  570. {
  571.     union REGS  regs;
  572.  
  573.     if (extendedflipping) {
  574.         regs.x.ax = 0x4F07;
  575.         regs.x.bx = 0x0000;
  576.         regs.x.cx = x;
  577.         regs.x.dx = y;
  578.         int86(0x10,®s,®s);
  579.         }
  580. }
  581.  
  582. long rgbColor(uchar r,uchar g,uchar b)
  583. /****************************************************************************
  584. *
  585. * Function:     rgbColor
  586. *
  587. * Returns:      Value representing the color. The value is converted from
  588. *               24 bit RGB space into the appropriate color for the
  589. *               video mode.
  590. *
  591. ****************************************************************************/
  592. {
  593.     return ((long)((r >> redAdjust) & redMask) << redPos)
  594.          | ((long)((g >> greenAdjust) & greenMask) << greenPos)
  595.          | ((long)((b >> blueAdjust) & blueMask) << bluePos);
  596. }
  597.  
  598. PUBLIC void line(int x1,int y1,int x2,int y2,long color)
  599. /****************************************************************************
  600. *
  601. * Function:     line
  602. * Parameters:   x1,y1       - First endpoint of line
  603. *               x2,y2       - Second endpoint of line
  604. *               color       - Color to draw the line in
  605. *
  606. * Description:  Scan convert a line segment using the MidPoint Digital
  607. *               Differential Analyser algorithm.
  608. *
  609. ****************************************************************************/
  610. {
  611.     int     d;                      /* Decision variable                */
  612.     int     dx,dy;                  /* Dx and Dy values for the line    */
  613.     int     Eincr,NEincr;           /* Decision variable increments     */
  614.     int     yincr;                  /* Increment for y values           */
  615.     int     t;                      /* Counters etc.                    */
  616.  
  617.     dx = ABS(x2 - x1);
  618.     dy = ABS(y2 - y1);
  619.  
  620.     if (dy <= dx) {
  621.  
  622.         /* We have a line with a slope between -1 and 1
  623.          *
  624.          * Ensure that we are always scan converting the line from left to
  625.          * right to ensure that we produce the same line from P1 to P0 as the
  626.          * line from P0 to P1.
  627.          */
  628.  
  629.         if (x2 < x1) {
  630.             t = x2; x2 = x1; x1 = t;    /* Swap X coordinates           */
  631.             t = y2; y2 = y1; y1 = t;    /* Swap Y coordinates           */
  632.             }
  633.  
  634.         if (y2 > y1)
  635.             yincr = 1;
  636.         else
  637.             yincr = -1;
  638.  
  639.         d = 2*dy - dx;              /* Initial decision variable value  */
  640.         Eincr = 2*dy;               /* Increment to move to E pixel     */
  641.         NEincr = 2*(dy - dx);       /* Increment to move to NE pixel    */
  642.  
  643.         putPixel(x1,y1,color);      /* Draw the first point at (x1,y1)  */
  644.  
  645.         /* Incrementally determine the positions of the remaining pixels
  646.          */
  647.  
  648.         for (x1++; x1 <= x2; x1++) {
  649.             if (d < 0) {
  650.                 d += Eincr;         /* Choose the Eastern Pixel         */
  651.                 }
  652.             else {
  653.                 d += NEincr;        /* Choose the North Eastern Pixel   */
  654.                 y1 += yincr;        /* (or SE pixel for dx/dy < 0!)     */
  655.                 }
  656.             putPixel(x1,y1,color);  /* Draw the point                   */
  657.             }
  658.         }
  659.     else {
  660.  
  661.         /* We have a line with a slope between -1 and 1 (ie: includes
  662.          * vertical lines). We must swap our x and y coordinates for this.
  663.          *
  664.          * Ensure that we are always scan converting the line from left to
  665.          * right to ensure that we produce the same line from P1 to P0 as the
  666.          * line from P0 to P1.
  667.          */
  668.  
  669.         if (y2 < y1) {
  670.             t = x2; x2 = x1; x1 = t;    /* Swap X coordinates           */
  671.             t = y2; y2 = y1; y1 = t;    /* Swap Y coordinates           */
  672.             }
  673.  
  674.         if (x2 > x1)
  675.             yincr = 1;
  676.         else
  677.             yincr = -1;
  678.  
  679.         d = 2*dx - dy;              /* Initial decision variable value  */
  680.         Eincr = 2*dx;               /* Increment to move to E pixel     */
  681.         NEincr = 2*(dx - dy);       /* Increment to move to NE pixel    */
  682.  
  683.         putPixel(x1,y1,color);      /* Draw the first point at (x1,y1)  */
  684.  
  685.         /* Incrementally determine the positions of the remaining pixels
  686.          */
  687.  
  688.         for (y1++; y1 <= y2; y1++) {
  689.             if (d < 0) {
  690.                 d += Eincr;         /* Choose the Eastern Pixel         */
  691.                 }
  692.             else {
  693.                 d += NEincr;        /* Choose the North Eastern Pixel   */
  694.                 x1 += yincr;        /* (or SE pixel for dx/dy < 0!)     */
  695.                 }
  696.             putPixel(x1,y1,color);  /* Draw the point                   */
  697.             }
  698.         }
  699. }
  700.  
  701. PUBLIC void writeText(int x,int y,uchar *str,long color)
  702. /****************************************************************************
  703. *
  704. * Function:     writeText
  705. * Parameters:   x,y     - Position to begin drawing string at
  706. *               str     - String to draw
  707. *
  708. * Description:  Draws a string using the BIOS 8x16 video font by plotting
  709. *               each pixel in the characters individually. This should
  710. *               work for all video modes.
  711. *
  712. ****************************************************************************/
  713. {
  714.     uchar           byte;
  715.     int             i,j,k,length,ch;
  716.     uchar           *font;
  717.  
  718.     font = getFontVec();
  719.     length = strlen(str);
  720.     for (k = 0; k < length; k++) {
  721.         ch = str[k];
  722.         for (j = 0; j < 16; j++) {
  723.             byte = *(font + ch * 16 + j);
  724.             for (i = 0; i < 8; i++) {
  725.                 if ((byte & 0x80) != 0)
  726.                     putPixel(x+i,y+j,color);
  727.                 byte <<= 1;
  728.                 }
  729.             }
  730.         x += 8;
  731.         }
  732. }
  733.